<template>
  <div class="dynamic-list">
    <NDataTable
      class="flex-1"
      v-model:checked-row-keys="localCheckedRowKeys"
      :remote="remote"
      :flex-height="flexHeight"
      :columns="processedColumns"
      :data="data"
      :row-key="rowKey"
      :loading="loading"
      :striped="striped"
      :estimated-row-count="itemCount"
      :row-class-name="rowClassName"
      :bordered="bordered"
      :scroll-x="scrollX"
      @update:checked-row-keys="handleSelectionChange"
    >
      <!-- 动态插槽 -->
      <template
        v-for="slotName in slotNames"
        :key="slotName"
        v-slot:[`${slotName}-cell`]="{ row, index }"
      >
        <slot :name="`${slotName}-cell`" :row="row" :index="index"></slot>
      </template>
    </NDataTable>

    <!-- 分页 -->
    <div class="mt-3 flex items-center justify-between" v-if="showPagination">
      <span v-if="showSelectionInfo">已选择&nbsp;{{ localCheckedRowKeys.length }}&nbsp;条</span>
      <NPagination
        :page="page"
        :page-size="pageSize"
        :item-count="itemCount"
        :size="paginationSize"
        :show-size-picker="showSizePicker"
        :show-quick-jumper="showQuickJumper"
        :page-sizes="pageSizes"
        @update:page="handlePageChange"
        @update:page-size="handlePageSizeChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { NDataTable, NPagination } from 'naive-ui'
import { ref, computed, watch } from 'vue'

import type { PaginationSizeOption } from 'naive-ui'

// Props
interface Props {
  // 表格数据
  data: any[]
  // 列配置
  columns: any[]
  // 行键
  rowKey: (row: any) => any
  // 加载状态
  loading?: boolean
  // 远程模式
  remote?: boolean
  // 弹性高度
  flexHeight?: boolean
  // 条纹状
  striped?: boolean
  // 边框
  bordered?: boolean
  // 横向滚动宽度
  scrollX?: number | string
  // 当前页码
  page?: number
  // 每页条数
  pageSize?: number

  // 总条数
  itemCount?: number
  // 是否显示分页
  showPagination?: boolean
  // 是否显示选择信息
  showSelectionInfo?: boolean
  // 分页尺寸
  paginationSize?: 'small' | 'medium' | 'large'
  // 是否显示页码大小选择器
  showSizePicker?: boolean
  // 是否显示快速跳转
  showQuickJumper?: boolean
  // 页码大小选项
  pageSizes?: Array<number | PaginationSizeOption>
  // 行类名
  rowClassName?: (row: any, index: number) => string
  // 选中的行键
  checkedRowKeys?: any[]
}

const props = withDefaults(defineProps<Props>(), {
  loading: false,
  remote: true,
  flexHeight: false,
  striped: true,
  bordered: false,
  scrollX: 1800,
  page: 1,
  pageSize: 2,
  itemCount: 0,
  showPagination: true,
  showSelectionInfo: true,
  paginationSize: 'medium',
  showSizePicker: true,
  showQuickJumper: true,
  pageSizes: () => [10, 20, 50, 100],
  rowClassName: () => '',
  checkedRowKeys: () => []
})

// Emits
interface Emits {
  // 选择变化
  (e: 'update:checkedRowKeys', value: any[]): void
  // 页码变化
  (e: 'update:page', value: number): void
  // 页大小变化
  (e: 'update:pageSize', value: number): void
}

const emit = defineEmits<Emits>()

// 本地选中的行键
const localCheckedRowKeys = ref<any[]>(props.checkedRowKeys)

// 监听外部选中行键变化
watch(
  () => props.checkedRowKeys,
  (newVal) => {
    localCheckedRowKeys.value = newVal
  },
  { deep: true }
)

// 获取所有需要的插槽名称
const slotNames = computed(() => {
  return props.columns
    .filter(column => column.title !== '' && column.key)
    .map(column => column.key as string)
})

// 处理后的列配置
const processedColumns = computed(() => {
  return props.columns
})

// 选择变化处理
function handleSelectionChange(keys: any[]) {
  emit('update:checkedRowKeys', keys)
}

// 页码变化处理
function handlePageChange(page: number) {
  emit('update:page', page)
}

// 页大小变化处理
function handlePageSizeChange(pageSize: number) {
  emit('update:pageSize', pageSize)
}
</script>

<style scoped>
.dynamic-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>
